﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using EdgeStatz.ESSystems.Objects;
using EdgeStatz.ModelEngine.DatabaseTools;
using EdgeStatz.ModelEngine.FolderTools;

namespace EdgeStatz
{
    public partial class OptionsDialog : Form
    {
        DBStructureEngine databaseEngine;
        FolderEngine folderEngine;

        public FolderEngine FolderEngine
        {
            get { return folderEngine; }
        }

        public DBStructureEngine DatabaseEngine
        {
            get { return databaseEngine; }
        }

        #region Database Variables
        Panel database_panel = new Panel();
        Button b_Validate = new Button();
        Button b_Script = new Button();
        Button b_Update = new Button();

        Label lbl_dbs1 = new Label();
        ListBox lb_enums = new ListBox();
        ListBox lb_values = new ListBox();
        TextBox tb_selectedVal = new TextBox();
        Button b_dbs_enum_Save = new Button();
        Button b_dbs_enum_Add = new Button();
        Button b_dbs_enum_Delete = new Button();
        #endregion

        #region General Variables
        Panel general_panel = new Panel();

        Label lbl_export = new Label();
        CheckBox chkb_recursive = new CheckBox();

        Label lbl_save_auto = new Label();
        CheckBox chkb_save_auto = new CheckBox();
        CheckBox chkb_save_request = new CheckBox();
        #endregion

        #region Web Variables
        Panel web_panel = new Panel();

        Label lbl_email = new Label();
        Label lbl_host = new Label();
        TextBox tb_host = new TextBox();
        Label lbl_port = new Label();
        TextBox tb_port = new TextBox();
        Label lbl_ssl = new Label();
        CheckBox chkb_ssl = new CheckBox();
        Label lbl_from = new Label();
        TextBox tb_from = new TextBox();
        Label lbl_useDefault = new Label();
        CheckBox chkb_useDefault = new CheckBox();
        Label lbl_accountName = new Label();
        TextBox tb_accountName = new TextBox();
        Label lbl_password = new Label();
        TextBox tb_password = new TextBox();
        #endregion

        #region MainDialog
        public OptionsDialog(DBStructureEngine databaseEngine, FolderEngine folderEngine)
        {
            if (databaseEngine == null || folderEngine == null)
                throw new ArgumentNullException("A model must be opened before the options can be viewed or changed.");
            this.databaseEngine = databaseEngine;
            this.folderEngine = folderEngine;

            InitializeComponent();
            database_panel.Dock = DockStyle.Fill;
            general_panel.Dock = DockStyle.Fill;
            web_panel.Dock = DockStyle.Fill;
        }

        private void b_Cancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }

        private void b_Ok_Click(object sender, EventArgs e)
        {
            Save_General();
            Save_Web();
            databaseEngine.SaveOptions();
            this.DialogResult = DialogResult.OK;
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count != 1)
                return;
            panel_Template.Controls.Clear();
            switch (listView1.SelectedItems[0].Text.ToUpper())
            {
                case "GENERAL":
                    panel_Template.Controls.Add(general_panel);
                    break;
                case "DATABASE":
                    panel_Template.Controls.Add(database_panel);
                    break;
                case "REPORTS":
                    break;
                case "SECURITY":
                    break;
                case "WEB":
                    panel_Template.Controls.Add(web_panel);
                    break;
            }
        }

        public new DialogResult ShowDialog()
        {
            if (SetDatabasePanel() && SetGeneralPanel() && SetWebPanel())
                return base.ShowDialog();
            return DialogResult.Abort;
        }
        #endregion

        #region General
        private bool SetGeneralPanel()
        {
            this.lbl_export.AutoSize = true;
            this.lbl_export.Text = "Export Options:";

            this.chkb_recursive.AutoSize = true;
            this.chkb_recursive.Name = "chkb_recursive";
            this.chkb_recursive.Text = "Recursive Export";
            this.chkb_recursive.Checked = databaseEngine.Options_Recursive;
            this.chkb_recursive.TabIndex = 1;

            this.lbl_save_auto.AutoSize = true;
            this.lbl_save_auto.Text = "Save Options:";

            this.chkb_save_auto.AutoSize = true;
            this.chkb_save_auto.Name = "chkb_save_auto";
            this.chkb_save_auto.Text = "Automatically save";
            this.chkb_save_auto.Checked = databaseEngine.Option_Save_Auto;
            this.chkb_save_auto.TabIndex = 2;

            this.chkb_save_request.AutoSize = true;
            this.chkb_save_request.Name = "chkb_save_request";
            this.chkb_save_request.Text = "Asks the user";
            this.chkb_save_request.Checked = databaseEngine.Option_Save_Request;
            this.chkb_save_request.TabIndex = 3;

            TableLayoutPanel _tablepanel = new TableLayoutPanel();
            _tablepanel.AutoScroll = true;
            _tablepanel.AutoSize = true;
            _tablepanel.ColumnCount = 2;
            _tablepanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
            _tablepanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
            _tablepanel.Controls.Add(this.lbl_export, 0, 0);
            _tablepanel.Controls.Add(this.chkb_recursive, 1, 1);
            _tablepanel.Controls.Add(this.lbl_save_auto, 0, 2);
            _tablepanel.Controls.Add(this.chkb_save_auto, 1, 3);
            _tablepanel.Controls.Add(this.chkb_save_request, 1, 5);
            _tablepanel.Dock = System.Windows.Forms.DockStyle.Fill;
            _tablepanel.Location = new System.Drawing.Point(0, 0);
            _tablepanel.Name = "_tablepanel";
            _tablepanel.RowCount = 6;
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.TabIndex = 0;

            general_panel.Controls.Add(_tablepanel);
            return true;
        }

        void Save_General()
        {
            databaseEngine.Options_Recursive = chkb_recursive.Checked;
            databaseEngine.Option_Save_Auto = chkb_save_auto.Checked;
            databaseEngine.Option_Save_Request = chkb_save_request.Checked;
        }
        #endregion

        #region Web
        private bool SetWebPanel()
        {
            this.lbl_email.Text = "Email Server Options:";
            this.lbl_email.AutoSize = true;

            this.lbl_host.Text = "Host Name:";
            this.lbl_host.AutoSize = true;

            this.tb_host.Text = databaseEngine.Options_EmailServer == null ? "" : databaseEngine.Options_EmailServer.Host;
            this.tb_host.Name = "tb_host";
            this.tb_host.TabIndex = 2;

            this.lbl_port.Text = "Port:";
            this.lbl_port.AutoSize = true;

            this.tb_port.Text = databaseEngine.Options_EmailServer == null ? "" : databaseEngine.Options_EmailServer.Port.ToString();
            this.tb_port.Name = "tb_port";
            this.tb_port.TabIndex = 3;

            this.chkb_ssl.Name = "chkb_ssl";
            this.chkb_ssl.Text = "Enable SSL";
            this.chkb_ssl.Checked = databaseEngine.Options_EmailServer == null ? false : databaseEngine.Options_EmailServer.EnableSsl;
            this.chkb_ssl.TabIndex = 4;

            this.lbl_from.Text = "From Address:";
            this.lbl_from.AutoSize = true;

            this.tb_from.Text = databaseEngine.Options_EmailServer == null ? "" : databaseEngine.Options_EmailServer.FromAddress;
            this.tb_from.Name = "tb_from";
            this.tb_from.TabIndex = 5;

            this.chkb_useDefault.Name = "chkb_useDefault";
            this.chkb_useDefault.Text = "Use Default Credentials";
            this.chkb_useDefault.Checked = databaseEngine.Options_EmailServer == null ? true : databaseEngine.Options_EmailServer.UseDefaultCredentials;
            this.chkb_useDefault.TabIndex = 6;
            this.chkb_useDefault.CheckedChanged += new EventHandler(chkb_useDefault_CheckedChanged);

            this.lbl_accountName.Text = "Account Name:";
            this.lbl_accountName.AutoSize = true;

            this.tb_accountName.Text = databaseEngine.Options_EmailServer == null ? "" : databaseEngine.Options_EmailServer.AccountName;
            this.tb_accountName.Name = "tb_accountName";
            this.tb_accountName.TabIndex = 7;

            this.lbl_password.Text = "Password:";
            this.lbl_password.AutoSize = true;

            this.tb_password.Text = databaseEngine.Options_EmailServer == null ? "" : databaseEngine.Options_EmailServer.Password;
            this.tb_password.Name = "tb_from";
            this.tb_password.UseSystemPasswordChar = true;
            this.tb_password.TabIndex = 8;

            TableLayoutPanel _tablepanel = new TableLayoutPanel();

            _tablepanel.AutoScroll = true;
            _tablepanel.AutoSize = true;
            _tablepanel.ColumnCount = 2;
            _tablepanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
            _tablepanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
            _tablepanel.Controls.Add(this.lbl_email, 0, 0);
            _tablepanel.Controls.Add(this.lbl_host, 0, 1);
            _tablepanel.Controls.Add(this.tb_host, 1, 1);
            _tablepanel.Controls.Add(this.lbl_port, 0, 2);
            _tablepanel.Controls.Add(this.tb_port, 1, 2);
            _tablepanel.Controls.Add(this.chkb_ssl, 1, 3);
            _tablepanel.Controls.Add(this.lbl_from, 0, 4);
            _tablepanel.Controls.Add(this.tb_from, 1, 4);
            _tablepanel.Controls.Add(this.chkb_useDefault, 1, 5);
            _tablepanel.Controls.Add(this.lbl_accountName, 0, 6);
            _tablepanel.Controls.Add(this.tb_accountName, 1, 6);
            _tablepanel.Controls.Add(this.lbl_password, 0, 7);
            _tablepanel.Controls.Add(this.tb_password, 1, 7);
            _tablepanel.Dock = System.Windows.Forms.DockStyle.Fill;
            _tablepanel.Location = new System.Drawing.Point(0, 0);
            _tablepanel.Name = "_tablepanel";
            _tablepanel.RowCount = 8;
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
            _tablepanel.TabIndex = 0;

            web_panel.Controls.Add(_tablepanel);
            return true;
        }

        void chkb_useDefault_CheckedChanged(object sender, EventArgs e)
        {
            if (chkb_useDefault.Checked)
            {
                tb_accountName.Enabled = false;
                tb_password.Enabled = false;
            }
            else
            {
                tb_accountName.Enabled = true;
                tb_password.Enabled = true;
            }
        }

        void Save_Web()
        {
            if (!tb_host.Text.Trim().Equals(""))
            {
                EmailServer ems = new EmailServer();
                ems.Host = tb_host.Text;
                ems.Port = Convert.ToInt32(tb_port.Text);
                ems.EnableSsl = chkb_ssl.Checked;
                ems.FromAddress = tb_from.Text;
                if (chkb_useDefault.Checked)
                    ems.UseDefaultCredentials = true;
                else
                {
                    ems.UseDefaultCredentials = false;
                    ems.AccountName = tb_accountName.Text;
                    ems.Password = tb_password.Text;
                }
                databaseEngine.Options_EmailServer = ems;
            }
        }
        #endregion

        #region Database
        private bool SetDatabasePanel()
        {
            this.b_Validate.Name = "b_Validate";
            this.b_Validate.Text = "Validate";
            this.b_Validate.Location = new Point(5, 5);
            this.b_Validate.Click +=new EventHandler(b_Validate_Click);
            
            this.b_Script.Name = "b_Script";
            this.b_Script.Text = "Get Script";
            this.b_Script.Location = new Point(85, 5);
            this.b_Script.Click += new EventHandler(b_Script_Click);

            this.b_Update.Name = "b_Update";
            this.b_Update.Text = "Update";
            this.b_Update.Location = new Point(165, 5);
            this.b_Update.Click += new EventHandler(b_Update_Click);

            this.lbl_dbs1.Text = "Enumerations: ";
            this.lbl_dbs1.AutoSize = true;
            this.lbl_dbs1.Location = new Point(5, 30);

            this.lb_enums.Size = new Size(175,200);
            this.lb_enums.Location = new Point(5, 55);
            this.lb_enums.SelectedIndexChanged += new EventHandler(lb_enums_SelectedIndexChanged);

            this.lb_values.Size = new Size(225,200);
            this.lb_values.Location = new Point(220, 55);
            this.lb_values.ValueMember = "Value";
            this.lb_values.DisplayMember = "Display";
            this.lb_values.ScrollAlwaysVisible = true;
            this.lb_values.SelectedIndexChanged += new EventHandler(lb_values_SelectedIndexChanged);

            this.tb_selectedVal.Name = "tb_selectedVal";
            this.tb_selectedVal.Size = new Size(225, 25);
            this.tb_selectedVal.Location = new Point(5, 260);

            this.b_dbs_enum_Add.Name = "b_dbs_enum_Add";
            this.b_dbs_enum_Add.Text = "Add New";
            this.b_dbs_enum_Add.Location = new Point(5, 290);
            this.b_dbs_enum_Add.Click += new EventHandler(b_dbs_enum_Add_Click);

            this.b_dbs_enum_Save.Name = "b_dbs_enum_Save";
            this.b_dbs_enum_Save.Text = "Save";
            this.b_dbs_enum_Save.Location = new Point(85,290);
            this.b_dbs_enum_Save.Click += new EventHandler(b_dbs_enum_Save_Click);

            this.b_dbs_enum_Delete.Name = "b_dbs_enum_Delete";
            this.b_dbs_enum_Delete.Text = "Delete";
            this.b_dbs_enum_Delete.Location = new Point(165, 290);
            this.b_dbs_enum_Delete.Click += new EventHandler(b_dbs_enum_Delete_Click);

            database_panel.Controls.Add(b_Validate);
            database_panel.Controls.Add(b_Script);
            database_panel.Controls.Add(b_Update);
            database_panel.Controls.Add(lbl_dbs1); 
            database_panel.Controls.Add(lb_enums);
            database_panel.Controls.Add(lb_values);
            database_panel.Controls.Add(tb_selectedVal);
            database_panel.Controls.Add(b_dbs_enum_Save);
            database_panel.Controls.Add(b_dbs_enum_Add);
            database_panel.Controls.Add(b_dbs_enum_Delete);

            if(databaseEngine.CheckDatabaseExists())
                RefreshEnumList();

            return true;
        }

        void b_dbs_enum_Delete_Click(object sender, EventArgs e)
        {
            EnumFolderDefinition sel_enumdef = null;
            foreach (EnumFolderDefinition ed in folderEngine.GetEnumFolderDefinitions())
                if (ed.Name.Equals(lb_enums.SelectedItem.ToString()))
                    sel_enumdef = ed;
            if (sel_enumdef == null)
                return;

            if (lb_values.SelectedIndex == -1)
                return;
            else
            {
                GlobalObjectsSQL.ExecuteNonQueryCommand("DELETE FROM [" + sel_enumdef.TableName + "] WHERE [" 
                    + sel_enumdef.ValueExp + "] = '" + ((DisplayValueObject)lb_values.SelectedItem).Value + "'");
            }
            lb_enums_SelectedIndexChanged(null, new EventArgs());
            b_dbs_enum_Add_Click(null, new EventArgs());
        }

        void lb_values_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lb_values.SelectedIndex == -1)
                return;
            tb_selectedVal.Text = ((DisplayValueObject)lb_values.SelectedItem).Display;
        }

        void lb_enums_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lb_enums.SelectedIndex == -1)
                return;
            EnumFolderDefinition sel_enumdef = null;
            foreach (EnumFolderDefinition ed in folderEngine.GetEnumFolderDefinitions())
            {
                if (ed.Name.Equals(lb_enums.SelectedItem.ToString()))
                {
                    sel_enumdef = ed;
                }
            }
            if (sel_enumdef == null)
                return;
            this.lb_values.Items.Clear();
            List<DisplayValueObject> dispValObjs = new List<DisplayValueObject> { };
            object[] reader = GlobalObjectsSQL.ExecuteReaderQueryCommand("SELECT [" + sel_enumdef.ValueExp + "], [" + sel_enumdef.DisplayExp + "] FROM [" +
                sel_enumdef.TableName + "] Order by [" + sel_enumdef.DisplayExp + "] asc");
            foreach (object obj in reader)
            {
                object[] obj_reader = (object[])obj;
                dispValObjs.Add(new DisplayValueObject(obj_reader[1].ToString(),obj_reader[0].ToString()));
            }
            this.lb_values.Items.AddRange(dispValObjs.ToArray());
        }

        void RefreshEnumList()
        {
            EnumFolderDefinition[] enumdefs = folderEngine.GetEnumFolderDefinitions();
            lb_enums.Items.Clear();
            foreach (EnumFolderDefinition ed in enumdefs)
                lb_enums.Items.Add(ed.Name);
            b_dbs_enum_Add_Click(null, new EventArgs());
        }

        void b_dbs_enum_Add_Click(object sender, EventArgs e)
        {
            if (lb_enums.SelectedIndex == -1)
                return;
            tb_selectedVal.Clear();
            lb_values.SelectedIndex = -1;
        }

        void b_dbs_enum_Save_Click(object sender, EventArgs e)
        {
            if(tb_selectedVal.Text.Trim().Equals(""))
                MessageBox.Show("Enum Display value cannot be empty");
            
            EnumFolderDefinition sel_enumdef = null;
            foreach (EnumFolderDefinition ed in folderEngine.GetEnumFolderDefinitions())
                if (ed.Name.Equals(lb_enums.SelectedItem.ToString()))
                    sel_enumdef = ed;
            if (sel_enumdef == null)
                return;

            if (lb_values.SelectedIndex == -1)
            {
                GlobalObjectsSQL.ExecuteNonQueryCommand("INSERT INTO " + sel_enumdef.TableName + " ([" +
                    sel_enumdef.DisplayExp + "]) VALUES ('" + tb_selectedVal.Text.Trim() + "')");
            }
            else
            {
                GlobalObjectsSQL.ExecuteNonQueryCommand("UPDATE [" + sel_enumdef.TableName + "] SET [" +
                    sel_enumdef.DisplayExp + "] = '" + tb_selectedVal.Text.Trim() + "' WHERE [" + sel_enumdef.ValueExp + "] = '" + ((DisplayValueObject)lb_values.SelectedItem).Value + "'");
            }
            lb_enums_SelectedIndexChanged(null, new EventArgs());
            b_dbs_enum_Add_Click(null, new EventArgs());
        }

        void b_Update_Click(object sender, EventArgs e)
        {
            databaseEngine.UpdateDatabaseAgainstModel();
            MessageBox.Show("Database is up to date.");
            RefreshEnumList();
        }

        void b_Script_Click(object sender, EventArgs e)
        {
            string text = "";
            string[] updatescript = databaseEngine.GetUpdateScriptDatabaseAgainstModel();
            if (updatescript == null)
            {
                MessageBox.Show("Database is up to date.");
                return;
            }
            foreach (string txt in updatescript)
                text += txt + "\n\n";

            MessageBox.Show(text);
        }

        void b_Validate_Click(object sender, EventArgs e)
        {
            string text = "";
            string[] updatescript = databaseEngine.ValidateDatabaseAgainstModel();
            if (updatescript == null)
            {
                MessageBox.Show("Database is up to date.");
                return;
            }
            foreach (string txt in updatescript)
                text += txt + "\n\n";

            MessageBox.Show(text);
        }
        #endregion
    }
}
